package com.fdb.efp.edoc.api.rest;

import com.fdb.basic.framework.core.constant.BaseConstant;
import com.fdb.basic.framework.core.constant.DataRuleType;
import com.fdb.basic.framework.core.constant.PubConstant;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.efp.e4a.service.facade.SRoleDataRuleService;
import com.fdb.efp.edoc.common.SysReportNameCNEnum;
import com.fdb.efp.edoc.service.ExportReportDataService;
import com.fdb.efp.edoc.service.bo.ExportReportConditionsVO;
import com.fdb.efp.edoc.service.bo.FileExportListVO;
import com.fdb.efp.edoc.service.facade.FileExportListService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;

@RestController
@RequestMapping("/api")
public class FileExportListController extends AbstractController {
	
	@Autowired
	@Qualifier("fileExportListService")
	private FileExportListService fileExportListService;

	@Autowired
	@Qualifier("sRoleDataRuleService")
	private SRoleDataRuleService sRoleDataRuleService;

	@Autowired
	private ExportReportDataService exportReportDataService;

	private static final String CHARSET_CODE = "UTF-8";

	@Value("${REPOETFILEPATH}")
	private String reportfilepath;

	@Value("${TIMEOUT_EXPORT}")
	private int timeoutExport;

//	@Autowired
//	@Qualifier("applicationThreadPool")
//	private ApplicationThreadPool2 threadPool;

	@Autowired
	@Qualifier("taskExecutor")
	private ThreadPoolTaskExecutor executor;

	/**
	 * 列表数据查询
	 * @param vo
	 * @return
	 */
	@RequestMapping(value="/file/export/lists", method=RequestMethod.POST)
	public @ResponseBody ResponseData<List<FileExportListVO>> queryFileExportListAll(@RequestBody FileExportListVO vo) {
		List<FileExportListVO> outputVo = null;
		Map<String,String> dataRuleTypeMap = sRoleDataRuleService.getDataRuleType(httpRequest.getRequestURI(), getUserRoles());
		vo.setPrdCodebyBaseInfo(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PRD_CODE));
		DataRuleType dataRuleType = DataRuleType.getDataRuleType(dataRuleTypeMap == null ? null:dataRuleTypeMap.get(PubConstant.PERMIS_TYPE));
		setUserInfoToVO(vo);
		// 根据权限方案调用不同的方案进行数据查询
		switch (dataRuleType) {
			case Owner:
				outputVo = fileExportListService.queryAllOwner(vo);
				break;
			case CurrOrg:
				outputVo = fileExportListService.queryAllCurrOrg(vo);
				break;
			case CurrDownOrg:
				outputVo = fileExportListService.queryAllCurrDownOrg(vo);
				break;
			default:
				outputVo = fileExportListService.queryAllOwner(vo);
				break;
		}
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键查询详情
	 * @return
	 */
	@RequestMapping(value="/file/export/list", method=RequestMethod.GET)
	public @ResponseBody ResponseData<FileExportListVO> queryByPk() {		
		FileExportListVO inVo = new FileExportListVO();
		FileExportListVO outputVo = fileExportListService.queryByPk(inVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键删除信息
	 * @param inFileExportListVo
	 * @return
	 */
	@RequestMapping(value="/file/export/list", method=RequestMethod.DELETE)
	public @ResponseBody
	ResponseData<Integer> deleteByPk(@RequestBody FileExportListVO inFileExportListVo) {
		int outputVo = fileExportListService.deleteByPk(inFileExportListVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 根据主键更新信息
	 * @param inFileExportListVo
	 * @return
	 */
	@RequestMapping(value="/file/export/list", method=RequestMethod.PUT)
	public @ResponseBody ResponseData<Integer> updateByPk(@RequestBody FileExportListVO inFileExportListVo) {		
		int outputVo = fileExportListService.updateByPk(inFileExportListVo);
		return getResponseData(outputVo);
		
	}
	
	/**
	 * 新增数据
	 * @param inFileExportListVo
	 * @return
	 */
	@RequestMapping(value="/file/export/list", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Integer> insertFileExportList(@RequestBody FileExportListVO inFileExportListVo) {
		int outputVo = fileExportListService.insertFileExportList(inFileExportListVo);
		return getResponseData(outputVo);
		
	}

	@RequestMapping(value="/file/export/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> fileExportListDownLoad(HttpServletResponse response, HttpServletRequest request,
																	 @RequestParam(value = "pkId", required = true) String pkId,
																	 @RequestParam(value = "filePath", required = true) String filePath) throws IOException {
		logger.info("======>下载导出文件开始，文件路径为:<======" + filePath);
		try {
			//根据文件绝对路径下载文件
			downloadFile(response, filePath);

			//更新下载信息
			updFileExportListVO(pkId, BaseConstant.STD_GENERAL_STATUS_001, "下载成功！");

		} catch (Exception e) {
			updFileExportListVO(pkId, BaseConstant.STD_GENERAL_STATUS_002, e.getMessage());
			e.printStackTrace();
			return getResponseData(null);
		}
		logger.info("======>下载导出文件结束，文件路径为:<======" + filePath);
		return getResponseData("downloadSuccess");
	}

	/**
	 *
	 * @param response
	 * @param filePath 文件绝对路径
	 * @throws Exception
	 */
	private void downloadFile(HttpServletResponse response, String filePath) throws Exception {
		File file = new File(filePath);
		InputStream inputStream = new FileInputStream(file);

		ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[10240];
		int length = -1;
		while ((length = inputStream.read(buffer, 0, buffer.length)) != -1) {
			baoStream.write(buffer, 0, length);
			baoStream.flush();
		}
		response.setContentType("application/json; charset=UTF-8");
		response.setHeader("Content-Disposition", "attachment;filename=" +  new String((file.getName()).getBytes("GBK"), "ISO8859-1"));
		response.setContentLength(baoStream.toByteArray().length);

		baoStream.writeTo(response.getOutputStream());

		if(baoStream != null)
			baoStream.close();
		if (inputStream != null)
			inputStream.close();
	}

	/**
	 *
	 * @param pkId 主键
	 * @param downloadStatus 下载状态
	 * @param statusDesc 下载状态描述
	 */
	private void updFileExportListVO(String pkId, String downloadStatus, String statusDesc){
		FileExportListVO fileExportListVO = new FileExportListVO();
		fileExportListVO.setPkId(pkId);
		fileExportListVO.setDownloadSts(downloadStatus);
		fileExportListVO.setDownloadStsDesc(statusDesc);
		fileExportListVO.setDownloadTime(TimeUtil.getCurrentDateTime());
		fileExportListVO.setDownloadUser(fileExportListVO.getLoginUserId());
		fileExportListVO.setDownloadUserName(this.getUserInfo().getUserName());
		fileExportListVO.setDownloadUserOrg(fileExportListVO.getLoginUserOrgCode());
		fileExportListVO.setDownloadUserOrgName(this.getUserInfo().getOrgInfo().getOrgName());
		int num = fileExportListService.updateByPk(fileExportListVO);
		if(num != 1){
			logger.error("根据参数:" + fileExportListVO.toString() + "更新下载信息出错！");
		}
	}

	@RequestMapping(value="/file/export/execute", method=RequestMethod.POST)
	public WebAsyncTask<String> exportReportDatas(@RequestBody ExportReportConditionsVO exportReportConditionsVO) throws Exception {
		int outputVo = 1;
		if (Objects.isNull(exportReportConditionsVO)) throw new Exception("参数没有表名！");

		setUserInfoToVO(exportReportConditionsVO);
		String exportTime = TimeUtil.getCurrentDateTime();
		//String fileName = SysReportNameCNEnum.RPT_ACC_LOAN.getValue() + exportTime.replace(":","").replace("-","").trim() + ".xlsx";
		String fileName = new StringBuffer()
				.append(SysReportNameCNEnum.getValue(exportReportConditionsVO.getSysReportName()))
				.append(exportTime.replace(":","").replace(" ", "").replace("-","").trim())
				.append(".xlsx")
				.toString();
		String filePath = new StringBuffer().append(reportfilepath).append("/").append(fileName).toString();

		exportReportConditionsVO.setFileName(fileName);
		exportReportConditionsVO.setFilePath(filePath);
		exportReportConditionsVO.setExportTime(exportTime);
		exportReportConditionsVO.setUserName(this.getUserInfo().getUserName());
		exportReportConditionsVO.setOrgName(this.getUserInfo().getOrgInfo().getOrgName());

		//插入一条"处理中"的导出数据
		exportReportDataService.insertFileExportInfo(exportReportConditionsVO, BaseConstant.STD_GENERAL_STATUS_003,"导出处理中");

		Callable<String> callable = () -> {
			//开始处理
			switch (exportReportConditionsVO.getSysReportName()) {
				case "rpt_acc_loan":
					try {
						//分页查询数据库写入excel
						exportReportDataService.writeDtas(exportReportConditionsVO, filePath, fileName);
						//更新导出信息
						exportReportDataService.updFileExportListExport(fileName, BaseConstant.STD_GENERAL_STATUS_001,"导出成功");
					} catch (Exception e) {
						e.printStackTrace();
						//更新导出信息
						exportReportDataService.updFileExportListExport(fileName, BaseConstant.STD_GENERAL_STATUS_002, e.getMessage());
					}
					break;
				default:
					break;
			}
			return "导出异步处理中，请点击右边“导出清单查看”按钮查看导出文件清单";
		};
		WebAsyncTask webAsyncTask = new WebAsyncTask(timeoutExport * 1000l, executor, callable);
		webAsyncTask.onTimeout(() ->{
			String msg = "导出异步处理超时，已超过配置的超时时间:" + timeoutExport + "s";
			exportReportDataService.updFileExportListExport(fileName, BaseConstant.STD_GENERAL_STATUS_002, msg);
			return msg;
		});
		webAsyncTask.onError(()->{
			String msg = "导出异步任务处理异常";
			exportReportDataService.updFileExportListExport(fileName, BaseConstant.STD_GENERAL_STATUS_002, msg);
			return msg;
		});

		return webAsyncTask;
	}

	@RequestMapping(value="/check/report/num", method=RequestMethod.POST)
	public @ResponseBody ResponseData<Integer> checkReportNum(@RequestBody ExportReportConditionsVO exportReportConditionsVO) {
		int output = 0;
		switch (exportReportConditionsVO.getSysReportName()) {
			case "rpt_acc_loan":
				output = exportReportDataService.countDatas(exportReportConditionsVO);
				break;

			default:
				break;
		}
		return getResponseData(output);
	}

	@RequestMapping(value="/query/file/export/list", method=RequestMethod.POST)
	public @ResponseBody ResponseData<List<FileExportListVO>> queryFileExportList(@RequestBody FileExportListVO vo) {
		List<FileExportListVO> output = fileExportListService.queryAllByCondition(vo);
		return getResponseData(output);
	}

}
